﻿// Decompiled with JetBrains decompiler
// Type: UnityEngine.SpookyHash
// Assembly: UnityEngine.CoreModule, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null
// MVID: E6AE6B5A-2752-4B07-9528-C8B77C62CE79
// Assembly location: C:\Users\windys\Unity\2021.3.39f1c1\Editor\Data\Managed\UnityEngine\UnityEngine.CoreModule.dll
// XML documentation location: C:\Users\windys\Unity\2021.3.39f1c1\Editor\Data\Managed\UnityEngine\UnityEngine.CoreModule.xml

using System;
using System.Runtime.InteropServices;
using Unity.Collections.LowLevel.Unsafe;

#nullable disable
namespace UnityEngine
{
  internal static class SpookyHash
  {
    private static readonly bool AllowUnalignedRead = SpookyHash.AttemptDetectAllowUnalignedRead();
    private const int k_NumVars = 12;
    private const int k_BlockSize = 96;
    private const int k_BufferSize = 192;
    private const ulong k_DeadBeefConst = 16045690984833335023;

    private static bool AttemptDetectAllowUnalignedRead()
    {
      string processorType = SystemInfo.processorType;
      return processorType == "x86" || processorType == "AMD64";
    }

    public static unsafe void Hash(void* message, ulong length, ulong* hash1, ulong* hash2)
    {
      if (length < 192UL)
      {
        SpookyHash.Short(message, length, hash1, hash2);
      }
      else
      {
        ulong* numPtr = stackalloc ulong[12];
        long num1;
        ulong num2 = (ulong) (num1 = (long) *hash1);
        ulong num3 = (ulong) num1;
        ulong num4 = (ulong) num1;
        ulong num5 = (ulong) num1;
        long num6;
        ulong num7 = (ulong) (num6 = (long) *hash2);
        ulong num8 = (ulong) num6;
        ulong num9 = (ulong) num6;
        ulong num10 = (ulong) num6;
        long num11;
        ulong num12 = (ulong) (num11 = -2401053088876216593L);
        ulong num13 = (ulong) num11;
        ulong num14 = (ulong) num11;
        ulong num15 = (ulong) num11;
        SpookyHash.U u = new SpookyHash.U((ushort*) message);
        ulong* source = (ulong*) ((IntPtr) u.p64 + (IntPtr) (length / 96UL * 12UL * 8UL));
        if (SpookyHash.AllowUnalignedRead || ((long) u.i & 7L) == 0L)
        {
          for (; u.p64 < source; u.p64 += 12)
            SpookyHash.Mix(u.p64, ref num5, ref num10, ref num15, ref num4, ref num9, ref num14, ref num3, ref num8, ref num13, ref num2, ref num7, ref num12);
        }
        else
        {
          for (; u.p64 < source; u.p64 += 12)
          {
            UnsafeUtility.MemCpy((void*) numPtr, (void*) u.p64, 96L);
            SpookyHash.Mix(numPtr, ref num5, ref num10, ref num15, ref num4, ref num9, ref num14, ref num3, ref num8, ref num13, ref num2, ref num7, ref num12);
          }
        }
        ulong size = length - (ulong) ((sbyte*) source - (sbyte*) message);
        UnsafeUtility.MemCpy((void*) numPtr, (void*) source, (long) size);
        SpookyHash.memset((void*) ((IntPtr) numPtr + (IntPtr) size), 0, 96UL - size);
        ((byte*) numPtr)[95] = (byte) size;
        SpookyHash.End(numPtr, ref num5, ref num10, ref num15, ref num4, ref num9, ref num14, ref num3, ref num8, ref num13, ref num2, ref num7, ref num12);
        *hash1 = num5;
        *hash2 = num10;
      }
    }

    private static unsafe void End(
      ulong* data,
      ref ulong h0,
      ref ulong h1,
      ref ulong h2,
      ref ulong h3,
      ref ulong h4,
      ref ulong h5,
      ref ulong h6,
      ref ulong h7,
      ref ulong h8,
      ref ulong h9,
      ref ulong h10,
      ref ulong h11)
    {
      h0 += *data;
      h1 += data[1];
      h2 += data[2];
      h3 += data[3];
      h4 += data[4];
      h5 += data[5];
      h6 += data[6];
      h7 += data[7];
      h8 += data[8];
      h9 += data[9];
      h10 += data[10];
      h11 += data[11];
      SpookyHash.EndPartial(ref h0, ref h1, ref h2, ref h3, ref h4, ref h5, ref h6, ref h7, ref h8, ref h9, ref h10, ref h11);
      SpookyHash.EndPartial(ref h0, ref h1, ref h2, ref h3, ref h4, ref h5, ref h6, ref h7, ref h8, ref h9, ref h10, ref h11);
      SpookyHash.EndPartial(ref h0, ref h1, ref h2, ref h3, ref h4, ref h5, ref h6, ref h7, ref h8, ref h9, ref h10, ref h11);
    }

    private static void EndPartial(
      ref ulong h0,
      ref ulong h1,
      ref ulong h2,
      ref ulong h3,
      ref ulong h4,
      ref ulong h5,
      ref ulong h6,
      ref ulong h7,
      ref ulong h8,
      ref ulong h9,
      ref ulong h10,
      ref ulong h11)
    {
      h11 += h1;
      h2 ^= h11;
      SpookyHash.Rot64(ref h1, 44);
      h0 += h2;
      h3 ^= h0;
      SpookyHash.Rot64(ref h2, 15);
      h1 += h3;
      h4 ^= h1;
      SpookyHash.Rot64(ref h3, 34);
      h2 += h4;
      h5 ^= h2;
      SpookyHash.Rot64(ref h4, 21);
      h3 += h5;
      h6 ^= h3;
      SpookyHash.Rot64(ref h5, 38);
      h4 += h6;
      h7 ^= h4;
      SpookyHash.Rot64(ref h6, 33);
      h5 += h7;
      h8 ^= h5;
      SpookyHash.Rot64(ref h7, 10);
      h6 += h8;
      h9 ^= h6;
      SpookyHash.Rot64(ref h8, 13);
      h7 += h9;
      h10 ^= h7;
      SpookyHash.Rot64(ref h9, 38);
      h8 += h10;
      h11 ^= h8;
      SpookyHash.Rot64(ref h10, 53);
      h9 += h11;
      h0 ^= h9;
      SpookyHash.Rot64(ref h11, 42);
      h10 += h0;
      h1 ^= h10;
      SpookyHash.Rot64(ref h0, 54);
    }

    private static void Rot64(ref ulong x, int k) => x = x << k | x >> 64 - k;

    private static unsafe void Short(void* message, ulong length, ulong* hash1, ulong* hash2)
    {
      ulong* destination = stackalloc ulong[24];
      SpookyHash.U u = new SpookyHash.U((ushort*) message);
      if (!SpookyHash.AllowUnalignedRead && (u.i & 7UL) > 0UL)
      {
        UnsafeUtility.MemCpy((void*) destination, message, (long) length);
        u.p64 = destination;
      }
      ulong num1 = length % 32UL;
      ulong h0 = *hash1;
      ulong h1 = *hash2;
      ulong h2 = 16045690984833335023;
      ulong h3 = 16045690984833335023;
      if (length > 15UL)
      {
        for (ulong* numPtr = (ulong*) ((IntPtr) u.p64 + (IntPtr) (length / 32UL * 4UL * 8UL)); u.p64 < numPtr; u.p64 += 4)
        {
          h2 += *u.p64;
          h3 += u.p64[1];
          SpookyHash.ShortMix(ref h0, ref h1, ref h2, ref h3);
          h0 += u.p64[2];
          h1 += u.p64[3];
        }
        if (num1 >= 16UL)
        {
          h2 += *u.p64;
          h3 += u.p64[1];
          SpookyHash.ShortMix(ref h0, ref h1, ref h2, ref h3);
          u.p64 += 2;
          num1 -= 16UL;
        }
      }
      h3 += length << 56;
      long num2 = (long) num1;
      if ((ulong) num2 <= 15UL)
      {
        switch ((uint) num2)
        {
          case 0:
            h2 += 16045690984833335023UL;
            h3 += 16045690984833335023UL;
            break;
          case 1:
            h2 += (ulong) *u.p8;
            break;
          case 2:
            h2 += (ulong) u.p8[1] << 8;
            goto case 1;
          case 3:
            h2 += (ulong) u.p8[2] << 16;
            goto case 2;
          case 4:
            h2 += (ulong) *u.p32;
            break;
          case 5:
            h2 += (ulong) u.p8[4] << 32;
            goto case 4;
          case 6:
            h2 += (ulong) u.p8[5] << 40;
            goto case 5;
          case 7:
            h2 += (ulong) u.p8[6] << 48;
            goto case 6;
          case 8:
            h2 += *u.p64;
            break;
          case 9:
            h3 += (ulong) u.p8[8];
            goto case 8;
          case 10:
            h3 += (ulong) u.p8[9] << 8;
            goto case 9;
          case 11:
            h3 += (ulong) u.p8[10] << 16;
            goto case 10;
          case 12:
            h3 += (ulong) u.p32[2];
            h2 += *u.p64;
            break;
          case 13:
            h3 += (ulong) u.p8[12] << 32;
            goto case 12;
          case 14:
            h3 += (ulong) u.p8[13] << 40;
            goto case 13;
          case 15:
            h3 += (ulong) u.p8[14] << 48;
            goto case 14;
        }
      }
      SpookyHash.ShortEnd(ref h0, ref h1, ref h2, ref h3);
      *hash1 = h0;
      *hash2 = h1;
    }

    private static void ShortMix(ref ulong h0, ref ulong h1, ref ulong h2, ref ulong h3)
    {
      SpookyHash.Rot64(ref h2, 50);
      h2 += h3;
      h0 ^= h2;
      SpookyHash.Rot64(ref h3, 52);
      h3 += h0;
      h1 ^= h3;
      SpookyHash.Rot64(ref h0, 30);
      h0 += h1;
      h2 ^= h0;
      SpookyHash.Rot64(ref h1, 41);
      h1 += h2;
      h3 ^= h1;
      SpookyHash.Rot64(ref h2, 54);
      h2 += h3;
      h0 ^= h2;
      SpookyHash.Rot64(ref h3, 48);
      h3 += h0;
      h1 ^= h3;
      SpookyHash.Rot64(ref h0, 38);
      h0 += h1;
      h2 ^= h0;
      SpookyHash.Rot64(ref h1, 37);
      h1 += h2;
      h3 ^= h1;
      SpookyHash.Rot64(ref h2, 62);
      h2 += h3;
      h0 ^= h2;
      SpookyHash.Rot64(ref h3, 34);
      h3 += h0;
      h1 ^= h3;
      SpookyHash.Rot64(ref h0, 5);
      h0 += h1;
      h2 ^= h0;
      SpookyHash.Rot64(ref h1, 36);
      h1 += h2;
      h3 ^= h1;
    }

    private static void ShortEnd(ref ulong h0, ref ulong h1, ref ulong h2, ref ulong h3)
    {
      h3 ^= h2;
      SpookyHash.Rot64(ref h2, 15);
      h3 += h2;
      h0 ^= h3;
      SpookyHash.Rot64(ref h3, 52);
      h0 += h3;
      h1 ^= h0;
      SpookyHash.Rot64(ref h0, 26);
      h1 += h0;
      h2 ^= h1;
      SpookyHash.Rot64(ref h1, 51);
      h2 += h1;
      h3 ^= h2;
      SpookyHash.Rot64(ref h2, 28);
      h3 += h2;
      h0 ^= h3;
      SpookyHash.Rot64(ref h3, 9);
      h0 += h3;
      h1 ^= h0;
      SpookyHash.Rot64(ref h0, 47);
      h1 += h0;
      h2 ^= h1;
      SpookyHash.Rot64(ref h1, 54);
      h2 += h1;
      h3 ^= h2;
      SpookyHash.Rot64(ref h2, 32);
      h3 += h2;
      h0 ^= h3;
      SpookyHash.Rot64(ref h3, 25);
      h0 += h3;
      h1 ^= h0;
      SpookyHash.Rot64(ref h0, 63);
      h1 += h0;
    }

    private static unsafe void Mix(
      ulong* data,
      ref ulong s0,
      ref ulong s1,
      ref ulong s2,
      ref ulong s3,
      ref ulong s4,
      ref ulong s5,
      ref ulong s6,
      ref ulong s7,
      ref ulong s8,
      ref ulong s9,
      ref ulong s10,
      ref ulong s11)
    {
      s0 += *data;
      s2 ^= s10;
      s11 ^= s0;
      SpookyHash.Rot64(ref s0, 11);
      s11 += s1;
      s1 += data[1];
      s3 ^= s11;
      s0 ^= s1;
      SpookyHash.Rot64(ref s1, 32);
      s0 += s2;
      s2 += data[2];
      s4 ^= s0;
      s1 ^= s2;
      SpookyHash.Rot64(ref s2, 43);
      s1 += s3;
      s3 += data[3];
      s5 ^= s1;
      s2 ^= s3;
      SpookyHash.Rot64(ref s3, 31);
      s2 += s4;
      s4 += data[4];
      s6 ^= s2;
      s3 ^= s4;
      SpookyHash.Rot64(ref s4, 17);
      s3 += s5;
      s5 += data[5];
      s7 ^= s3;
      s4 ^= s5;
      SpookyHash.Rot64(ref s5, 28);
      s4 += s6;
      s6 += data[6];
      s8 ^= s4;
      s5 ^= s6;
      SpookyHash.Rot64(ref s6, 39);
      s5 += s7;
      s7 += data[7];
      s9 ^= s5;
      s6 ^= s7;
      SpookyHash.Rot64(ref s7, 57);
      s6 += s8;
      s8 += data[8];
      s10 ^= s6;
      s7 ^= s8;
      SpookyHash.Rot64(ref s8, 55);
      s7 += s9;
      s9 += data[9];
      s11 ^= s7;
      s8 ^= s9;
      SpookyHash.Rot64(ref s9, 54);
      s8 += s10;
      s10 += data[10];
      s0 ^= s8;
      s9 ^= s10;
      SpookyHash.Rot64(ref s10, 22);
      s9 += s11;
      s11 += data[11];
      s1 ^= s9;
      s10 ^= s11;
      SpookyHash.Rot64(ref s11, 46);
      s10 += s0;
    }

    private static unsafe void memset(void* dst, int value, ulong numberOfBytes)
    {
      ulong num1 = (ulong) (uint) (value | value);
      ulong* numPtr1 = (ulong*) dst;
      ulong num2 = numberOfBytes >> 3;
      for (ulong index = 0; index < num2; ++index)
        *(long*) ((IntPtr) numPtr1 + (IntPtr) (index * 8UL)) = (long) num1;
      dst = (void*) numPtr1;
      numberOfBytes -= num2;
      byte* numPtr2 = stackalloc byte[4]
      {
        (byte) (value & 15),
        (byte) (value >>> 4 & 15),
        (byte) (value >>> 8 & 15),
        (byte) (value >>> 12 & 15)
      };
      byte* numPtr3 = (byte*) dst;
      ulong num3 = numberOfBytes;
      for (ulong index = 0; index < num3; ++index)
        numPtr3[index] = numPtr2[index % 4UL];
    }

    [StructLayout(LayoutKind.Explicit)]
    private struct U(ushort* p8)
    {
      [FieldOffset(0)]
      public unsafe byte* p8 = (byte*) p8;
      [FieldOffset(0)]
      public unsafe uint* p32 = (uint*) null;
      [FieldOffset(0)]
      public unsafe ulong* p64 = (ulong*) null;
      [FieldOffset(0)]
      public ulong i = 0;
    }
  }
}
